import axios from 'axios'
import type { AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage } from 'element-plus'
import { appConfig } from '@/config/AppConfig'
import { ErrorCode, handleError } from '@/enum/ErrorCode'

const httpConfig = appConfig().httpConfig

/**
 * 创建请求实例
 */
const http = axios.create({
  // 请求基础地址
  baseURL: httpConfig.baseURL,
  // 请求超时时间，默认60s
  timeout: httpConfig.timeout,
  // 请求头参数配置
  headers: httpConfig.headers
})

// 添加请求拦截器 在发请求之前处理一下
http.interceptors.request.use((config: any) => {
  return config
}, (error:any) => {
  ElMessage.error(error.message)
  return Promise.reject(error)
})

// 添加响应拦截器 在得到数据之后处理一下
http.interceptors.response.use((data: any) => {
  // 二进制数据
  if(data.data instanceof Blob){
    return data;
  }

  // 异常处理
  handleError(data.data as Result)

  return data;
}, (error: any) => {
  ElMessage.error(error.message)
  return Promise.reject(error);
})

/**
 * 请求响应数据体
 */
export type Result<T = any> = {
  msg: string
  code: ErrorCode
  data: T
}

export default <T> (config: AxiosRequestConfig) => {
  // 指定promise实例成功之后的回调函数的第一个参数的类型为Response<T>
  return new Promise<Result<T>>((resolve, reject) => {
    // instance是我们在上面创建的axios的实例
    // 我们指定instance.request函数的第一个泛型为Response，并把Response的泛型指定为函数的泛型T
    // 第二个泛型AxiosResponse的data类型就被自动指定为Response<T>
    // AxiosResponse从axios中导出的，也可以不指定，TS会自动类型推断
    http.request<Result<T>>(config).then((response: AxiosResponse<Result<T>>) => {
      // response类型就是AxiosResponse<Response<T>>，而data类型就是我们指定的Response<T>
      // 请求成功后就我们的数据从response取出并使返回的promise实例的状态变为成功的
      resolve(response.data)
    }).catch((error :any) => {
      // 请求失败的处理
      reject(error)
    })
  })
}